package main

import (
	"fmt"
	"math/rand"
	"time"
)

/*
	练习三：
	1.time包
	2.defer关键字和recover处理错误
	3.数组、数组的遍历
	4.切片，切片的遍历
	5.排序：冒泡排序
	6.查找：顺序查找、二分查找
	7.二维数组
	8.map、map的遍历、map切片
*/

func main() {
	/*
		编写一段代码来统计 函数test01 执行的时间
	*/
	start := time.Now().Unix()
	test01()
	end := time.Now().Unix()
	fmt.Printf("耗时%v\n", end-start)

	/*
		defer+recover处理错误
	*/
	//defer func() {
	//	if err := recover(); err != nil {
	//		fmt.Printf("err=%v\n", err)
	//		fmt.Println("程序报错，待处理。。。")
	//	}
	//}()
	//num1 := 10
	//num2 := 0
	//res := num1 / num2
	//fmt.Println(res)

	/*
		创建一个byte类型的26个元素的数组，分别 放置'A'-'Z‘。使用for循环访问所有元素并打印出来。提示：字符数据运算 'A'+1 -> 'B'
	*/
	var testChars [26]byte
	for i := 0; i < 26; i++ {
		testChars[i] = 'A' + byte(i)
	}
	for i := 0; i < 26; i++ {
		fmt.Printf("%c\n", testChars[i])
	}

	/*
		请求出一个数组的最大值，并得到对应的下标。(冒泡算法)
	*/
	var intArray [6]int = [6]int{0, -10, 6, 27, 30, 100}
	var maxNum = intArray[0]
	var maxNumIndex = 0
	for i := 0; i < len(intArray); i++ {
		if maxNum < intArray[i] {
			maxNum = intArray[i]
			maxNumIndex = i
		}
	}
	fmt.Printf("maxNum=%v,maxNumIndex=%v\n", maxNum, maxNumIndex)

	/*
		请求出一个数组的和和平均值。for-range
	*/
	var intArr [6]int = [6]int{-10, 5, 9, 30, 57, -30}
	sum := 0
	for _, i := range intArr {
		sum += i
	}
	fmt.Printf("数组的和sum=%v，平均值为：%v\n", sum, float64(sum)/float64(len(intArray)))

	/*
		随机生成五个数，并将其反转打印 , 复杂应用.
	*/
	var intArr3 [6]int
	rand.Seed(time.Now().UnixNano())
	for i := 0; i < len(intArr3); i++ {
		intArr3[i] = rand.Intn(100)
	}
	fmt.Printf("交换前数组%v\n", intArr3)
	temp := 0
	for i := 0; i < len(intArr3)/2; i++ {
		temp = intArr3[len(intArr3)-i-1]
		intArr3[len(intArr3)-i-1] = intArr3[i]
		intArr3[i] = temp
	}
	fmt.Printf("交换后数组%v\n", intArr3)

	/*
		切片练习：编写一个函数 fbn(n int) ，要求完成
		1) 可以接收一个 n int
		2) 能够将斐波那契的数列放到切片中
		3) 提示, 斐波那契的数列形式:
		arr[0] = 1; arr[1] = 1; arr[2]=2; arr[3] = 3; arr[4]=5; arr[5]=8
	*/
	res := fbn(25)
	fmt.Printf("res=%v\n", res)

	/*
		冒泡排序
	*/
	var arr = [5]int{7, -1, 20, 12, 88}
	BubbleSort(&arr)
	fmt.Printf("arr=%v\n", arr)

	/*
		顺序查找：
		有一个数列：白眉鹰王、金毛狮王、紫衫龙王、青翼蝠王
		猜数游戏：从键盘中任意输入一个名称，判断数列中是否包含此名称【顺序查找】
	*/
	//方法一：
	//nameList := [4]string{"白眉鹰王", "金毛狮王", "紫衫龙王", "青翼蝠王"}
	//var name = ""
	//fmt.Println("输入要查找的人名。。。")
	//fmt.Scanf("%v\n", &name)
	//
	//for i := 0; i < len(nameList); i++ {
	//	if nameList[i] == name {
	//		fmt.Printf("找到了%v，位于第%v位\n", name, i)
	//		break
	//	} else if i == len(nameList)-1 {
	//		fmt.Printf("没有找到%v\n", name)
	//	}
	//}
	////方法二：
	//index := -1
	//for i := 0; i < len(nameList); i++ {
	//	if name == nameList[i] {
	//		index = i
	//	}
	//}
	//if index != -1 {
	//	fmt.Printf("找到了%v，位于第%v位\n", name, index)
	//} else {
	//	fmt.Printf("没有找到%v\n", name)
	//}

	/*
		二分查找
		请对一个有序数组 {1,8, 10, 89, 1000, 1234}进行二分查找 ，输入一个数看看该数组是否存
		在此数，并且求出下标，如果没有就提示"没有这个数"
	*/
	newArr := [6]int{1, 8, 10, 89, 1000, 1234}
	BinaryFind(&newArr, 0, 5, 6)

	/*
		二维数组：
		定义二维数组，用于保存三个班，每个班五名同学成绩，
		并求出每个班级平均分、以及所有班级平均分
	*/
	//var scores [3][5]float64
	////循环输入成绩
	//for i := 0; i < len(scores); i++ {
	//	for j := 0; j < len(scores[i]); j++ {
	//		fmt.Printf("请输入%v班第%v位同学的成绩\n", i+1, j+1)
	//		fmt.Scanln(&scores[i][j])
	//	}
	//}
	//totalSum := 0.0
	//for i := 0; i < len(scores); i++ {
	//	sum := 0.0
	//	for j := 0; j < len(scores[i]); j++ {
	//		sum += scores[i][j]
	//	}
	//	totalSum += sum
	//	fmt.Printf("第%v班级的总分是%v，平均分为%v\n", i+1, sum, sum/float64(len(scores[i])))
	//}
	//fmt.Printf("所有班级的总分是%v，平均分为%v\n", totalSum, totalSum/15)

	/*
		map：
		练习：演示一个key-value 的value是map的案例
		比如：我们要存放3个学生信息, 每个学生有 name和sex 信息思路: 	map[string]map[string]string
	*/

	studentMap := make(map[string]map[string]string)
	studentMap["student1"] = make(map[string]string, 3)
	studentMap["student1"]["name"] = "jerry"
	studentMap["student1"]["age"] = "18"
	studentMap["student1"]["sex"] = "男"

	studentMap["student2"] = make(map[string]string, 3)
	studentMap["student2"]["name"] = "mary"
	studentMap["student2"]["age"] = "20"
	studentMap["student2"]["sex"] = "女"

	studentMap["student3"] = make(map[string]string, 3)
	studentMap["student3"]["name"] = "tom"
	studentMap["student3"]["age"] = "19"
	studentMap["student3"]["sex"] = "男"

	fmt.Println(studentMap)
	//map遍历  for-range
	for k1, v1 := range studentMap {
		for k2, v2 := range v1 {
			fmt.Printf("%v:%v:%v\n", k1, k2, v2)
		}
	}
	//map切片
	//使用一个map来记录monster的信息 name 和 age, 也就是说一个monster对应一个map,并且妖怪的个数可以动态的增加=>map切片
	var monsters []map[string]string
	monsters = make([]map[string]string, 3)
	monsters[0] = make(map[string]string, 2)
	monsters[0]["name"] = "黄眉大王"
	monsters[0]["age"] = "1800"

	monsters[1] = make(map[string]string, 2)
	monsters[1]["name"] = "牛魔王"
	monsters[1]["age"] = "8000"
	fmt.Println(monsters)
	newMonsters := map[string]string{
		"name": "蜘蛛精",
		"age":  "500",
	}
	monsters = append(monsters, newMonsters)
	fmt.Println(monsters)

	/*
		练习:
		1) 使用 map[string]map[string]sting 的map类型
		2) key: 表示用户名，是唯一的，不可以重复
		3) 如果某个用户名存在，就将其密码修改"888888"，如果不存在就增加这个用户信息,（包括昵称nickname 和 密码pwd）。
		4) 编写一个函数 modifyUser(users map[string]map[string]sting, name string) 完成上述功能
	*/
	users := make(map[string]map[string]string, 8)
	users["jerry"] = make(map[string]string, 2)
	users["jerry"]["nickname"] = "刚子"
	users["jerry"]["pwd"] = "00000000"

	modifyUser(users, "smith")
	modifyUser(users, "james")

	fmt.Println(users)
}

//time包使用
func test01() {
	str := "hello world"
	for i := 0; i < 100000; i++ {
		fmt.Printf("%v-%v\n", i, str)
	}
}

//切片练习
func fbn(n int) []uint64 {
	testSlice := make([]uint64, n)
	testSlice[0] = 1
	testSlice[1] = 1

	for i := 2; i < n; i++ {
		testSlice[i] = testSlice[i-1] + testSlice[i-2]
	}
	return testSlice
}

//冒泡排序示例
func BubbleSort(arr *[5]int) {
	temp := 0
	for i := 0; i < len(*arr); i++ {
		for j := 0; j < len(*arr)-i-1; j++ {
			if (*arr)[j] > (*arr)[j+1] {
				temp = (*arr)[j]
				(*arr)[j] = (*arr)[j+1]
				(*arr)[j+1] = temp
			}
		}
	}
}

//二分查找
func BinaryFind(arr *[6]int, leftIndex, rightIndex, findVal int) {
	if leftIndex > rightIndex {
		fmt.Println("找不到")
		return
	}
	middle := (leftIndex + rightIndex) / 2
	if (*arr)[middle] > findVal {
		BinaryFind(arr, leftIndex, middle-1, findVal)
	} else if (*arr)[middle] < findVal {
		BinaryFind(arr, middle+1, rightIndex, findVal)
	} else {
		fmt.Printf("找到了，下标为%v\n", middle)
	}
}

func modifyUser(users map[string]map[string]string, name string) {
	_, ok := users[name]
	if ok {
		users[name]["pwd"] = "888888"
	} else {
		users[name] = make(map[string]string, 2)
		users[name]["nickname"] = "业主" + name
		users[name]["pwd"] = "888888"
	}
}
